/*
 * @Author: zhang zhijiang 2824735304@qq.com
 * @Date: 2025-04-16 15:34:41
 * @LastEditors: zhang zhijiang 2824735304@qq.com
 * @LastEditTime: 2025-04-17 17:37:44
 * @FilePath: /linux/test_4_16/udpserver.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include <iostream>
#include <string>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <strings.h>
#include <arpa/inet.h>
#include <memory>
#include <unistd.h>
#include <vector>
#include <functional>
#include <unordered_map>
using namespace std;
using std::string;
static std::string defaultip = "0.0.0.0.";
static size_t defaultport = 8080;
static int Size = 1024;
typedef function<string(const string &)> func_t; //
class server
{

public:
    void parted_user(const string &clientip, uint16_t &clientport, const sockaddr_in &client)
    {
        if (usermap.find(clientip) == usermap.end())
        {
            usermap[clientip] = client;
            cout << "join a new user :" << "[" << clientip << ":" << clientport << "]";
        }
    }
    void broadcast(string info)
    {
        for(auto user:usermap)
        {
            socklen_t len = sizeof(user.second);
            sendto(sockfd, info.c_str(), info.size(), 0, (const sockaddr *)&user, len);
        }
    }
    server(uint16_t port = defaultport, string ip = defaultip) : sockfd(0), _port(port), _ip(ip), _isrunning(false)
    {
    }
    ~server()
    {
        if (sockfd > 0)
            close(sockfd);
    }
    void init()
    {
        sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd < 0)
            exit(2);
        struct sockaddr_in local;
        bzero(&local, sizeof(local));
        // local.sin_addr.s_addr =inet_addr(_ip.c_str()) ;   //1. string->unint  2. 网络字节序
        local.sin_addr.s_addr = htonl(INADDR_ANY); // 随便IP地址都可以
        local.sin_family = AF_INET;
        local.sin_port = htons(_port); // 网络字节序
        socklen_t len = sizeof(local);
        int n = bind(sockfd, (const sockaddr *)&local, len); // 绑定端口
        if (n < 0)
            exit(1);
        cout << "bind success" << endl;
    }
    void run( )
    {
        sockaddr_in client;
        char inbuffer[Size];
        _isrunning = true;
        socklen_t len = sizeof(client);
        // cout<<1<<endl;
        while (_isrunning)
        {
            size_t n = recvfrom(sockfd, inbuffer, sizeof(inbuffer) - 1, 0, (sockaddr *)&client, &len);
            string clientip = inet_ntoa(client.sin_addr);
            uint16_t clientport = ntohs(client.sin_port);
            parted_user(clientip, clientport, client);
            inbuffer[n] = 0; // 字符串末尾置0
             // 处理数据
            string info = "get a message from IP:";
            info+= clientip;
            info+=clientport;
            info+=":";
            info+=inbuffer;
            //cout<<info<<endl;
            //string res = func(inbuffer);
            broadcast(info);
        }
    }

private:
    size_t sockfd;
    uint16_t _port;
    std::string _ip;
    bool _isrunning;
    unordered_map<string, sockaddr_in> usermap;
};